package com.changgou.user.controller;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.exceptions.ClientException;
import com.changgou.entity.*;
import com.changgou.user.config.TokenDecode;
import com.changgou.user.pojo.User;
import com.changgou.user.service.UserService;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/****
 * @Author:admin
 * @Description:
 * @Date 2019/6/14 0:18
 *****/

@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private TokenDecode tokenDecode;
    @Autowired
    private RedisTemplate redisTemplate;
    /***
     * User分页条件搜索实现
     * @param user
     * @param page
     * @param size
     * @return
     */
    @PostMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@RequestBody(required = false)  User user, @PathVariable  int page, @PathVariable  int size){
        //调用UserService实现分页条件查询User
        PageInfo<User> pageInfo = userService.findPage(user, page, size);
        return new Result(true,StatusCode.OK,"查询成功",pageInfo);
    }

    /***
     * User分页搜索实现
     * @param page:当前页
     * @param size:每页显示多少条
     * @return
     */
    @GetMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@PathVariable  int page, @PathVariable  int size){
        //调用UserService实现分页查询User
        PageInfo<User> pageInfo = userService.findPage(page, size);
        return new Result<PageInfo>(true,StatusCode.OK,"查询成功",pageInfo);
    }

    /***
     * 多条件搜索品牌数据
     * @param user
     * @return
     */
    @PostMapping(value = "/search" )
    public Result<List<User>> findList(@RequestBody(required = false)  User user){
        //调用UserService实现条件查询User
        List<User> list = userService.findList(user);
        return new Result<List<User>>(true,StatusCode.OK,"查询成功",list);
    }

    /***
     * 根据ID删除品牌数据
     * @param id
     * @return
     */
    // @PreAuthorize("hasAnyAuthority('admin')")
    @DeleteMapping(value = "/{id}" )
    public Result delete(@PathVariable String id){
        //调用UserService实现根据主键删除
        userService.delete(id);
        return new Result(true,StatusCode.OK,"删除成功");
    }

    /***
     * 修改User数据
     * @param user
     * @param id
     * @return
     */
    @PutMapping(value="/{id}")
    public Result update(@RequestBody  User user,@PathVariable String id){
        //设置主键值
        user.setUsername(id);
        //调用UserService实现修改User
        userService.update(user);
        return new Result(true,StatusCode.OK,"修改成功");
    }

    /***
     * 新增User数据
     * @param user
     * @return
     */
    @PostMapping
    public Result add(@RequestBody   User user){
        //调用UserService实现添加User
        userService.add(user);
        return new Result(true,StatusCode.OK,"添加成功");
    }

    /***
     * 根据ID查询User数据
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<User> findById(@PathVariable String id){
        //调用UserService实现根据主键查询User
        User user = userService.findById(id);
        return new Result<User>(true,StatusCode.OK,"查询成功",user);
    }

    /***
     * 查询User全部数据
     * @return
     */
    @GetMapping
    public Result<List<User>> findAll(HttpServletRequest request){
        // 测试登录成功后,请求头中是否有令牌信息
        String token = request.getHeader("Authorization");
        System.out.println("获取到的令牌信息为:" + token);

        //调用UserService实现查询所有User
        List<User> list = userService.findAll();
        return new Result<List<User>>(true, StatusCode.OK,"查询成功",list) ;
    }

    /**
     * 用户登录  废弃了  (登录不需要了)   之前讲jwt的时候
     * @param username
     * @param password
     * @return
     */
    @GetMapping("/login")
    public Result login(String username, String password, HttpServletResponse resp) {
        User user = userService.findById(username);
        if(user != null && BCrypt.checkpw(password, user.getPassword())) {
            // 设置令牌信息
            Map<String, Object> userinfo = new HashMap<>();
            userinfo.put("role", "USER");
            userinfo.put("success", "SUCCESS");
            userinfo.put("username", username);
            String jwt = JwtUtil.createJWT(UUID.randomUUID().toString(), JSON.toJSONString(userinfo), null);

            // 登录成功,把token响应到cookie中
            Cookie cookie = new Cookie("Authorization", jwt);
            resp.addCookie(cookie);
            return new Result(true, StatusCode.OK, "登录成功",jwt);
        }
        return new Result(false, StatusCode.LOGINERROR, "用户名或密码错误");
    }


    // 增加积分
    @RequestMapping("/point/add")
    public Result addPoint(String username, int point){
        int count = userService.addPoint(username, point);
        if (count>0) {
            return new Result(true, StatusCode.OK, "添加积分成功");
        }
        return new Result(false, StatusCode.ERROR, "添加积分失败");
    }

    //获取登录用户
    public User getUser() {
        //获取用户名
        String username = tokenDecode.getUsername();
        //查找用户
        return userService.findById(username);
    }
    //发送短信验证码
    @RequestMapping("/sendValidateCode")
    public Result sendValidateCode() {
        //获取登录的用户
        User user = getUser();
        String phone = user.getPhone();
        //生成验证码
        Integer code = ValidateCodeUtils.generateValidateCode(4);
        try {
            //发送短信验证码 有0.5元短信费
            SMSUtils.sendShortMessage(SMSUtils.VALIDATE_CODE,phone,code.toString());
            System.out.println("发送的短信验证码是: " + code);
        } catch (Exception e) {
            e.printStackTrace();
            //验证码发送失败
            return new Result(false,StatusCode.ERROR,"验证码发送失败,请稍后再试!");
        }
        //将生成的验证码存入redis
        redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
        //验证码发送成功
        return new Result(true,StatusCode.OK,"验证码发送成功!",code);
    }
    //验证密码长度规则
    @RequestMapping("/validatePassword")
    public Result validatePassword (@RequestParam(name = "password") String password) {
        if (password == null || password.length() == 0) {
            return new Result(false,StatusCode.ERROR,"密码必须包含必须包含数字,字母或字符至少两种,且在8-16位之间");
        }
        String check = "^(?!^(\\d+|[a-zA-Z]+|[~!@#$%^&*?/]+)$)^[\\w~!@#$%^&*?/]{8,16}$";
        Pattern regex = Pattern.compile(check);
        if (regex.matcher(password).matches()) {
            return new Result(true,StatusCode.OK,"密码ok");
        } else {
            return new Result(false,StatusCode.ERROR,"密码必须包含必须包含数字,字母或字符至少两种,且在8-16位之间");
        }
    }
    // 安全设置 修改密码
    @RequestMapping("/changePassword")
    public Result changePassword(@RequestParam Map<String,String> map) {
        try {
            //获取页面输入的密码
            String password = map.get("password");
            //密码判空一致 前端页面处理
            //将密码加密后保存
            String encode = new BCryptPasswordEncoder().encode(password);
            //获取输入的验证码
            String code = map.get("code");
            //获取登录的用户
            User user = getUser();
            String phone = user.getPhone();
            //获取redis中的验证码
            Integer validateCode = (Integer) redisTemplate.opsForValue().get(phone);
            if (code != null && code.equals(validateCode+"")) {
                //验证码一样 修改密码到数据库
                user.setPassword(encode);
                userService.update(user);
            } else {
                return new Result(false,StatusCode.ERROR,"修改密码失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new Result(true,StatusCode.OK,"修改密码成功");
    }

    public static void main(String[] args) {
        String password = "123456";
        //将密码加密后保存
        String encode = new BCryptPasswordEncoder().encode(password);
        System.out.println(encode);
    }

}
